using DLGCY_FixedWifi;
using DotNet.Utilities.ConsoleHelper;
using ManagedNativeWifi;
using Newtonsoft.Json;
using PropertyChanged;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;
using System.Timers;
using System.Windows;
using System.Windows.Input;
using DotNet.Utilities;
using WPFPractice.Utils;
using WPFTemplateLib.UserControls;
using WPFTemplateLib.WpfHelpers;
using Timer = System.Timers.Timer;

namespace WPFTemplate.ViewModels
{
    [AddINotifyPropertyChangedInterface]
    public class MainWindowViewModel : MyBindableBase
    {
        #region 成员

        private Timer _Timer = new Timer() { Interval = 1, AutoReset = true };

        /// <summary>
        /// 需要固定 Wifi 的实例
        /// </summary>
        private AvailableNetworkPack _fixedWifiPack;

        /// <summary>
        /// 固定 Wifi 的 ProfileRadioPack
        /// </summary>
        private ProfileRadioPack _profileRadio;

        #endregion

        #region 绑定

        /// <summary>
        /// 配置
        /// </summary>
        public ConfigItems Configs { get; set; }

        /// <summary>
        /// 底部状态栏信息
        /// </summary>
        public string Status { get; set; } = "";

        /// <summary>
        /// 弹窗VM;
        /// </summary>
        public ConfirmBoxViewModel DialogVm { get; set; } = new ConfirmBoxViewModel();

        /// <summary>
        /// Wifi 接口列表
        /// </summary>
        public List<InterfaceConnectionInfo> InterfaceList { get; set; } = new List<InterfaceConnectionInfo>();

        /// <summary>
        /// 选中的接口
        /// </summary>
        public InterfaceConnectionInfo SelectedInterface { get; set; }

        /// <summary>
        /// Wifi列表
        /// </summary>
        public List<AvailableNetworkPack> WifiList { get; set; }

        /// <summary>
        /// 点击选中的 Wifi 项
        /// </summary>
        public AvailableNetworkPack SelectedWifi { get; set; }

        /// <summary>
        /// 选中 Wifi 详情
        /// </summary>
        public string SelectedWifiDetail { get; set; }

        /// <summary>
        /// 选中 Wifi 的 Profile 详情
        /// </summary>
        public string SelectedWifiProfile { get; set; }

        /// <summary>
        /// 配置区是否展开
        /// </summary>
        public bool IsConfigAreaExpanded { get; set; }

        #endregion

        public MainWindowViewModel()
        {
            Console.SetOut(new ConsoleWriter(s =>
            {
                ShowInfoUc(s);
            }));

            SetCommandMethod();

            LoadConfigCommand.Execute(false);

            ShowInfoUc($"Wifi 固定器 [{AssemblyHelper.AssemblyFileVersion}]");

            _Timer.Elapsed += new ElapsedEventHandler(TimerHandler);

            Configs.PropertyChanged += ConfigsOnPropertyChanged;
        }

        #region Command

        /// <summary>
        /// 保存配置命令
        /// </summary>
        public ICommand SaveConfigCommand { get; set; }

        /// <summary>
        /// 载入配置命令
        /// </summary>
        public ICommand LoadConfigCommand { get; set; }

        /// <summary>
        /// 关于弹窗命令
        /// </summary>
        public ICommand AboutCommand { get; set; }

        /// <summary>
        /// 命令：窗口载入事件转命令
        /// </summary>
        public ICommand LoadedCmd { get; set; }

        /// <summary>
        /// 刷新命令
        /// </summary>
        public ICommand RefreshCmd { get; set; }

        /// <summary>
        /// 命令：固定 Wifi
        /// </summary>
        public ICommand FixedWifiCmd { get; set; }

        /// <summary>
        /// 命令：开启监控
        /// </summary>
        public ICommand StartCmd { get; set; }

        /// <summary>
        /// 命令：停止监控
        /// </summary>
        public ICommand StopCmd { get; set; }

        #endregion

        /// <summary>
        /// 命令方法赋值(在构造函数中调用)
        /// </summary>
        private void SetCommandMethod()
        {
            SaveConfigCommand ??= new RelayCommand(o => true, async o =>
            {
                if (ConfigManager.SaveConfig(Configs))
                {
                    await ConfirmBoxHelper.ShowMessage(DialogVm, "保存配置成功");
                }
                else
                {
                    await ConfirmBoxHelper.ShowMessage(DialogVm, "保存配置失败");
                }
            });

            LoadConfigCommand ??= new RelayCommand(o => true, async o =>
            {
                var result = ConfigManager.LoadConfig<ConfigItems>();
                Configs = result.Value;
                if (result.IsSucceed)
                {
                    if (o as bool? != false)
                    {
                        await ConfirmBoxHelper.ShowMessage(DialogVm, "载入配置成功");
                    }
                }
                else
                {
                    await ConfirmBoxHelper.ShowMessage(DialogVm, "载入配置失败");
                }
            });

            AboutCommand ??= new RelayCommand(o => true, o =>
            {
                new AboutWindow().ShowDialog();
            });

            LoadedCmd ??= new RelayCommand(o => true, p =>
            {
                RoutedEventArgs args = p as RoutedEventArgs;
                RefreshCmd.Execute(null);

                if (Configs.IsAutoMonitor)
                {
                    StartCmd.Execute(null);
                }

                #region 检查开机自启

                bool hasStartupTask = TaskSchedulerHelper.IsExistStartupTask();
                if (Configs.IsStartupWithSys && !hasStartupTask)
                {
                    TaskSchedulerHelper.SwitchStartupWithSystem(true, Configs.IsStartupBeforeLogon);
                }

                if (!Configs.IsStartupWithSys && hasStartupTask)
                {
                    TaskSchedulerHelper.SwitchStartupWithSystem(false);
                }

                #endregion
            });

            RefreshCmd ??= new RelayCommand(o => true, async o =>
            {
                ScanWifi();

                if (!string.IsNullOrWhiteSpace(Configs.FixedWifi))
                {
                    var selected = WifiList.FirstOrDefault(x => x.Ssid.ToString() == Configs.FixedWifi);
                    if (selected != null)
                    {
                        SelectedWifi = selected;
                    }
                }
            });

            FixedWifiCmd ??= new RelayCommand(o => true, o =>
            {
                if (SelectedWifi == null)
                {
                    ToastToWindowCmd.Execute(new List<object> { "请先选择一项" });
                    return;
                }

                Configs.FixedWifi = SelectedWifi.Ssid.ToString();
                Console.WriteLine($"已将【{Configs.FixedWifi}】设置为需要固定的 Wifi。如需在下次开启软件时仍记住该设置，请点击【保存配置】按钮。");
                IsConfigAreaExpanded = true;
            });

            StartCmd ??= new RelayCommand(o => true, p =>
            {
                if (string.IsNullOrWhiteSpace(Configs.FixedWifi))
                {
                    Console.WriteLine("未设置需要固定的 Wifi，无法开启监控。");
                    return;
                }

                _fixedWifiPack = WifiList.FirstOrDefault(x => x.Ssid.ToString() == Configs.FixedWifi);
                if (_fixedWifiPack == null)
                {
                    Console.WriteLine("当前不存在需要固定的 Wifi 信号，无法开启监控。可刷新检查后再试。");
                    return;
                }

                _profileRadio = GetProfileRadio(_fixedWifiPack);
                if (_profileRadio == null)
                {
                    Console.WriteLine("当前不存在需要固定的 Wifi 的 Profile 信息，无法开启监控。需手动连接过 Wifi 后（产生 Profile）再使用本软件。");
                    return;
                }

                if (_Timer.Enabled)
                {
                    Console.WriteLine($"目前监控已处于开启状态，无需重复操作");
                    return;
                }

                // 设置Interval为想要的间隔时间。
                _Timer.Interval = 1000 * Configs.CheckInterval;
                _Timer.Start();
                Console.WriteLine($"【开启监控成功】检测间隔时间为 {Configs.CheckInterval}s");
                // 手动触发可以直接调用，不需要将Interval设置为1
                TimerHandler(_Timer, default);
            });

            StopCmd ??= new RelayCommand(o => true, p =>
            {
                if (!_Timer.Enabled)
                {
                    Console.WriteLine($"目前监控已处于关闭状态，无需重复操作");
                    return;
                }

                _Timer.Stop();
                Console.WriteLine($"【关闭监控成功】{Environment.NewLine}");
            });
        }

        #region 属性变动

        /// <summary>
        /// ViewModel 中的属性变动处理
        /// </summary>
        protected override void PropertyChangedHandle(object sender, PropertyChangedEventArgs e)
        {
            try
            {
                switch (e.PropertyName)
                {
                    case nameof(SelectedWifi):
                        {
                            SelectedWifiChanged();
                            break;
                        }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }

        /// <summary>
        /// 正在被还原的属性名列表
        /// </summary>
        private List<string> _revertPropertyList = new List<string>();

        /// <summary>
        /// 配置类中的属性变动处理
        /// </summary>
        private void ConfigsOnPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            try
            {
                if (_revertPropertyList.Contains(e.PropertyName))
                {
                    _revertPropertyList.Remove(e.PropertyName);
                    return;
                }

                switch (e.PropertyName)
                {
                    case nameof(Configs.IsStartupWithSys):
                        {
                            bool switchResult = TaskSchedulerHelper.SwitchStartupWithSystem(Configs.IsStartupWithSys, Configs.IsStartupBeforeLogon);
                            if (!switchResult)
                            {
                                _revertPropertyList.Add(e.PropertyName);
                                Configs.IsStartupWithSys = !Configs.IsStartupWithSys;
                            }
                            break;
                        }
                    case nameof(Configs.IsStartupBeforeLogon):
                        {
                            //该项在启动时不方便判断状态，所以直接保存
                            SaveConfigCommand.Execute(null);
                            break;
                        }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }

        /// <summary>
        /// 选中 Wifi 变动处理方法
        /// </summary>
        private void SelectedWifiChanged()
        {
            GetWifiDetail();
            GetProfileDetail();
        }

        #endregion

        #region 方法

        /// <summary>
        /// 是否有 Wifi 接口
        /// </summary>
        /// <returns>true/false</returns>
        private bool HasWifiInterface()
        {
            NetworkInterface[] nfaces = NetworkInterface.GetAllNetworkInterfaces();
            var wifiInterfaces = nfaces.Where(x => x.NetworkInterfaceType == NetworkInterfaceType.Wireless80211);
            if (wifiInterfaces.Any())
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// 扫描 Wifi 信号
        /// </summary>
        private void ScanWifi()
        {
            if (!HasWifiInterface())
            {
                return;
            }

            InterfaceList.Clear();
            InterfaceList.Add(null);
            InterfaceList.AddRange(NativeWifi.EnumerateInterfaceConnections().ToList());

            WifiList = NativeWifi.EnumerateAvailableNetworks().ToList();
        }

        /// <summary>
        /// 获取 Wifi 详情
        /// </summary>
        private void GetWifiDetail()
        {
            if (SelectedWifi != null)
            {
                SelectedWifiDetail = GetWifiDetailStr(SelectedWifi);
            }
            else
            {
                SelectedWifiDetail = string.Empty;
            }
        }

        /// <summary>
        /// 获取 Wifi 详情的字符串
        /// </summary>
        /// <param name="availableNetwork"></param>
        /// <returns></returns>
        private string GetWifiDetailStr(AvailableNetworkPack availableNetwork)
        {
            StringBuilder wifiDetail = new StringBuilder();
            wifiDetail.AppendLine($"ProfileName：{availableNetwork.ProfileName}");
            wifiDetail.AppendLine($"Ssid：{availableNetwork.Ssid}");
            wifiDetail.AppendLine($"AuthenticationAlgorithm：{availableNetwork.AuthenticationAlgorithm}");
            wifiDetail.AppendLine($"BssType：{availableNetwork.BssType}");
            wifiDetail.AppendLine($"CipherAlgorithm：{availableNetwork.CipherAlgorithm}");
            wifiDetail.AppendLine($"IsSecurityEnabled：{availableNetwork.IsSecurityEnabled}");
            wifiDetail.AppendLine($"SignalQuality：{availableNetwork.SignalQuality}");
            wifiDetail.AppendLine($"Interface：{JsonConvert.SerializeObject(availableNetwork.Interface)}");

            return wifiDetail.ToString();
        }

        /// <summary>
        /// 获取 Profile 详情
        /// </summary>
        private void GetProfileDetail()
        {
            if (SelectedWifi == null)
            {
                SelectedWifiProfile = string.Empty;
                return;
            }

            var profileRadio = GetProfileRadio(SelectedWifi);
            if (profileRadio != null)
            {
                SelectedWifiProfile = GetProfileDetailStr(profileRadio);
            }
            else
            {
                SelectedWifiProfile = string.Empty;
            }
        }

        /// <summary>
        /// 获取 ProfileRadio
        /// </summary>
        /// <param name="availableNetworkPack"></param>
        /// <returns>(可能为null)</returns>
        private ProfileRadioPack GetProfileRadio(AvailableNetworkPack availableNetworkPack)
        {
            string profileName = availableNetworkPack.ProfileName;
            var profileRadioList = NativeWifi.EnumerateProfileRadios().ToList();
            var profileRadio = profileRadioList.FirstOrDefault(x => x.Name == profileName || x.Document.Name == profileName);
            return profileRadio;
        }

        /// <summary>
        /// 获取 Profile 详情的字符串
        /// </summary>
        /// <param name="profileRadio"></param>
        /// <returns></returns>
        private string GetProfileDetailStr(ProfileRadioPack profileRadio)
        {
            StringBuilder wifiDetail = new StringBuilder();
            wifiDetail.AppendLine($"ProfileName：{profileRadio.Name}");
            wifiDetail.AppendLine($"ProfileType：{profileRadio.ProfileType}");
            wifiDetail.AppendLine($"Band：{profileRadio.Band}");
            wifiDetail.AppendLine($"Channel：{profileRadio.Channel}");
            wifiDetail.AppendLine($"Frequency：{profileRadio.Frequency}");
            wifiDetail.AppendLine($"IsConnected：{profileRadio.IsConnected}");
            wifiDetail.AppendLine($"IsRadioOn：{profileRadio.IsRadioOn}");
            wifiDetail.AppendLine($"LinkQuality：{profileRadio.LinkQuality}");
            wifiDetail.AppendLine($"SignalQuality：{profileRadio.SignalQuality}");
            wifiDetail.AppendLine($"PhyType：{profileRadio.PhyType}");
            wifiDetail.AppendLine($"Position：{profileRadio.Position}");
            wifiDetail.AppendLine($"Document：{JsonConvert.SerializeObject(profileRadio.Document)}");

            return wifiDetail.ToString();
        }

        /// <summary>
        /// 定时器任务
        /// </summary>
        private async void TimerHandler(object source, ElapsedEventArgs e)
        {
            try
            {
                //刷新连接状态;
                _profileRadio = GetProfileRadio(_fixedWifiPack);
                if (_profileRadio.IsConnected)
                {
                    //OutputThreadId();
                    Console.WriteLine("该 Wifi 已连接，无需操作");
                    return;
                }

                //OutputThreadId();
                Console.WriteLine($"即将尝试连接【{_fixedWifiPack.Ssid}】...");
                bool result = await NativeWifi.ConnectNetworkAsync(_fixedWifiPack.Interface.Id, 
                    _fixedWifiPack.ProfileName, _fixedWifiPack.BssType, TimeSpan.FromSeconds(5));
                //OutputThreadId();
                Console.WriteLine($"连接结果：{(result ? "成功" : "失败")}");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }

        /// <summary>
        /// 输出线程号
        /// </summary>
        private void OutputThreadId()
        {
            var thread = Thread.CurrentThread;
            ShowInfoUc($"[线程号：{thread.ManagedThreadId}] ");
        }

        #endregion
    }
}
